package gotengine

import (
	"context"
	"strings"

	"gitee.com/tommickey/gose/v3/gose/gotcache"
	"gitee.com/tommickey/gose/v3/gose/gotengine/engine"
	"gitee.com/tommickey/gose/v3/gose/gotlib"
	"gitee.com/tommickey/gose/v3/internal/app/common/global"
	"github.com/gogf/gf/v2/frame/g"
)

const (
	FieldFlagPre = "{{"
	FieldFlagSuf = "}}"
	FixParamName = "P"
	PoolMinLen   = 1
	PoolMaxLen   = 10
	EM           = 1
)

// RunEngineRuleOnce 创建并执行一次规则引擎
func RunEngineRuleOnce(ruleString string, ParamsMap map[string]string, apiOuter map[string]interface{}) (retMap map[string]interface{}, err error) {
	PMap := make(map[string]interface{})
	PMap["P"] = ParamsMap
	gotlib.LogDB(strings.Repeat("=", 80))
	gotlib.LogDB("业务参数：", PMap)
	//gotlib.LogIG("apis参数：", FixParamName, apiOuter[FixParamName])
	gotlib.LogDB("apis函数：", apiOuter)

	oncePool, err := engine.NewGenginePool(PoolMinLen, PoolMaxLen, EM, ruleString, apiOuter)
	if err != nil {
		gotlib.LogE(gotlib.StrAddLineNumber(ruleString))
		gotlib.LogE("RunEngineRuleOnce NewGenginePool Fail:", err)
		return
	}

	err, retMap = oncePool.Execute(PMap, false)
	if err != nil {
		gotlib.LogE(gotlib.StrAddLineNumber(ruleString))
		gotlib.LogE("RunEngineRuleOnce Execute Fail:", err)
	}
	gotlib.LogDB("返回结果：", retMap)
	gotlib.LogDB(strings.Repeat("=", 80))
	return retMap, err
}

// CacheRunEngineConfigOnce 运行配置一次 //Todo Cache功能待开发完成
func CacheRunEngineConfigOnce(ctx context.Context, configCode, configDescription, configString, configCache string, AppParams map[string]string) (result interface{}, err error) {

	//return RunEngineConfigOnce(configCode, configDescription, configString, AppParams, mapAPI)

	//
	// 如果configCache=="0",不做Cache检查，直接执行
	if configCache == "0" {
		mapAPI := GetDefaultEngineAPIs()
		return RunEngineConfigOnce(configCode, configDescription, configString, AppParams, mapAPI)
	}

	// configCache=="1", 检查cache结果;
	cacheKey := gotlib.StrJoin("", global.SysConfigEngine, configCode)

	result = gotcache.GetOrSetFunc(ctx, cacheKey, func(ctx context.Context) (interface{}, error) {
		mapAPI := GetDefaultEngineAPIs()
		return RunEngineConfigOnce(configCode, configDescription, configString, AppParams, mapAPI)
	}, 0)

	return
	/*	result, err = GetCacheMapByKey(cacheKey)
		if err == nil && result != nil { //找到Cache结果
			return
		}
		//没有找到Cache值，计算结果，并进行Cache
		mapAPI := GetDefaultEngineAPIs()
		result, err = RunEngineConfigOnce(configCode, configDescription, configString, AppParams, mapAPI)
		return*/
}

func GetResultNoCache(configCode, configDescription, configString string, AppParams map[string]string, mapAPI map[string]interface{}) (result interface{}, err error) {
	result, err = RunEngineConfigOnce(configCode, configDescription, configString, AppParams, mapAPI)
	return
}

func GetCacheMapByKey(cacheKey string) (result interface{}, err error) {

	return nil, nil
}

// RunEngineConfigOnce 运行配置一次,需要先初始化好 apis := GetDefaultEngineAPIs()
func RunEngineConfigOnce(configCode, configDescription, configString string, AppParams map[string]string, apis map[string]interface{}) (result interface{}, err error) {
	// 系统默认传递的参数进行更换#^#变量
	configString = ConfigStringReplaceEngineMap(configString, AppParams, apis)

	// 如果需要，可以在此处做SQL反注入的处理

	// 代码转换为标准执行格式
	ruleString := gotlib.StrJoin("", "\nrule \"", configCode, "\" \"", configDescription, "\"\nbegin\n",
		configString, "\nend")
	gotlib.LogIB("!!!!!!!!执行配置引擎：", configCode, configDescription, "!!!!!!!!")
	resMap, err := RunEngineRuleOnce(ruleString, AppParams, apis)
	if err != nil {
		return nil, nil
	}
	return resMap[configCode], nil
}

// RunContentEngine 适配老程序调用该函数，新功能直接调用：RunEngineConfigOnce
func RunContentEngine(contentString string, contentName string, mapAPI map[string]interface{}, Params g.MapStrStr) (result interface{}, err error) {
	// 适配老程序
	mapAPI = AddDefaultEngineAPIs(mapAPI)
	return RunEngineConfigOnce(contentName, contentName, contentString, Params, mapAPI)
}

// ConfigStringReplaceEngineMap 根据paramsMap，apis里的内容，对SQL语句中的变量进行替换。
func ConfigStringReplaceEngineMap(engineString string, paramsMap map[string]string, apis map[string]interface{}) string {
	// 判断是否包含{{}}
	if strings.Index(engineString, FieldFlagPre) < 0 ||
		strings.Index(engineString[strings.Index(engineString, FieldFlagPre):], FieldFlagSuf) < 0 {
		return engineString
	}
	// 获取替换map内容
	gotlib.LogD("engineString:\n", engineString)

	for k, v := range paramsMap {
		p := strings.Join([]string{FieldFlagPre, k, FieldFlagSuf}, "")
		engineString = strings.ReplaceAll(engineString, p, strings.Join([]string{v}, ""))
	}

	_, ok := apis[FixParamName]
	if ok {
		fixMap := apis[FixParamName].(map[string]interface{})
		for k, v := range fixMap {
			p := strings.Join([]string{FieldFlagPre, k, FieldFlagSuf}, "")
			engineString = strings.ReplaceAll(engineString, p, strings.Join([]string{gotlib.String(v)}, ""))
		}
	}

	//gotlib.LogD("Format engineString:", engineString)
	return engineString
}

//func RunContentEngineOld(contentString string, contentName string, mapAPI map[string]interface{}, Params g.MapStrStr) (result interface{}, err error) {
//	//glog.Info("配置引擎执行：=======》》》》", contentName)
//
//	//获取到要执行的内容configContent后，内容转换
//	configContent := gotlib.FormatSQLMap(contentString, Params)
//
//	configContent = strings.Join([]string{"Rule \"", contentName, "\" \"", contentName, "\"\n",
//		"begin\n",
//		configContent,
//		"\nend"}, "")
//	mapAPI["Println"] = fmt.Println
//	mapAPI["QueryMap"] = gotengine.QueryMap
//	mapAPI["Int64"] = gconv.Int64
//	mapAPI["Float64"] = gconv.Float64
//	mapAPI["String"] = gconv.String
//	mapAPI["InAS"] = library.In
//	mapAPI["Index"] = strings.Index
//	mapAPI["Split"] = strings.Split
//	mapAPI["LenAS"] = library.LenAS
//	mapAPI["LenAM"] = library.LenAM
//	mapAPI["LenAInt64"] = library.LenAInt64
//	mapAPI["LenS"] = library.LenS
//	mapAPI["Mid"] = library.Mid
//	mapAPI["Marshal"] = json.Marshal
//	mapAPI["Unmarshal"] = json.Unmarshal
//	mapAPI["DateTimeFun"] = library.DateTimeFun
//	mapAPI["DateTimeSub"] = library.DateTimeSub
//	mapAPI["FieldFormat"] = library.FieldFormat
//
//	Params["NowTime"] = gconv.String(gtime.Now())
//	mapAPI["Params"] = Params
//
//	// todo Tommy 此处需要进一步改造
//	gEngine, err := library.InitGEngineService(10, 20, 1, configContent, mapAPI)
//	if err != nil {
//		return "配置引擎初始化失败：" + contentName, err
//	}
//	response, err := gEngine.RunEngineRule([]string{contentName}, "")
//	if err != nil {
//		return "配置引擎执行失败" + contentName, err
//	}
//	return response[contentName], nil
//	return
//}
